package com.charging.system.controller;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSONObject;
import com.charging.common.constant.Constants;
import com.charging.common.utils.DateUtils;
import com.charging.common.utils.ImageUtils;
import com.charging.common.utils.uuid.UUID;
import com.charging.system.domain.KxChargingRecord;
import com.charging.system.domain.KxChargingScheme;
import com.charging.system.domain.KxUserInfo;
import com.charging.system.service.IKxChargingRecordService;
import com.charging.system.service.IKxChargingSchemeService;
import com.charging.system.service.IKxUserInfoService;
import io.swagger.annotations.ApiOperation;
import org.apache.catalina.mbeans.SparseUserDatabaseMBean;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.charging.common.annotation.Log;
import com.charging.common.core.controller.BaseController;
import com.charging.common.core.domain.AjaxResult;
import com.charging.common.enums.BusinessType;
import com.charging.system.domain.KxEquip;
import com.charging.system.service.IKxEquipService;
import com.charging.common.utils.poi.ExcelUtil;
import com.charging.common.core.page.TableDataInfo;

/**
 * 设备管理Controller
 *
 * @author charging
 * @date 2024-04-12
 */
@RestController
@RequestMapping("/system/equip")
public class KxEquipController extends BaseController
{
    @Resource
    private IKxEquipService kxEquipService;
    @Resource
    private IKxChargingRecordService kxChargingRecordService;
    @Resource
    private IKxChargingSchemeService kxChargingSchemeService;
    @Resource
    private IKxUserInfoService kxUserInfoService;

    /**
     * 查询设备管理列表
     */
    @PreAuthorize("@ss.hasPermi('system:equip:list')")
    @GetMapping("/list")
    public TableDataInfo list(KxEquip kxEquip)
    {
        startPage();
        List<KxEquip> list = kxEquipService.selectKxEquipList(kxEquip);
        return getDataTable(list);
    }

    /**
     * 导出设备管理列表
     */
    @PreAuthorize("@ss.hasPermi('system:equip:export')")
    @Log(title = "设备管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, KxEquip kxEquip)
    {
        List<KxEquip> list = kxEquipService.selectKxEquipList(kxEquip);
        ExcelUtil<KxEquip> util = new ExcelUtil<KxEquip>(KxEquip.class);
        util.exportExcel(response, list, "设备管理数据");
    }

    /**
     * 获取设备管理详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:equip:query')")
    @GetMapping(value = "/{equipId}")
    public AjaxResult getInfo(@PathVariable("equipId") Long equipId)
    {
        return success(kxEquipService.selectKxEquipByEquipId(equipId));
    }

    /**
     * 新增设备管理
     */
    @PreAuthorize("@ss.hasPermi('system:equip:add')")
    @Log(title = "设备管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody KxEquip kxEquip)
    {

        KxChargingScheme kxChargingScheme = kxChargingSchemeService.selectKxChargingSchemeByChargingSchemeId(kxEquip.getChargingSchemeId());
        if(kxEquip.getEquipType() ==1 && kxChargingScheme.getType()!=1){
            return AjaxResult.error("二轮充电桩只能选择二轮桩充电方案");
        }
        if(kxEquip.getEquipType() !=1 && kxChargingScheme.getType() ==1){
            return AjaxResult.error("汽车桩不能选择二轮桩方案");
        }
        return toAjax(kxEquipService.insertKxEquip(kxEquip));
    }

    /**
     * 修改设备管理
     */
    @PreAuthorize("@ss.hasPermi('system:equip:edit')")
    @Log(title = "设备管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody KxEquip kxEquip)
    {
        return toAjax(kxEquipService.updateKxEquip(kxEquip));
    }

    /**
     * 删除设备管理
     */
    @PreAuthorize("@ss.hasPermi('system:equip:remove')")
    @Log(title = "设备管理", businessType = BusinessType.DELETE)
	@DeleteMapping("/{equipIds}")
    public AjaxResult remove(@PathVariable Long[] equipIds)
    {
        return toAjax(kxEquipService.deleteKxEquipByEquipIds(equipIds));
    }

    /**
     * 按功率充电请求今接口
     * @param equipNo 设备编号
     * @param channelNo 插座号
     * @param planChargingTime 充电时长 0 为充满自停
     * @return
     */
    @RequestMapping(value="/openChannelByTime",method= RequestMethod.POST)
    public AjaxResult openChannelByTime(String equipNo,int channelNo ,@RequestParam(name="planChargingTime",defaultValue="0")int planChargingTime,
                                          @RequestParam(name="chargingFullNotStop",defaultValue="1") int chargingFullNotStop) {
        //检查用户是否正在充电，一般前端就控制了
        KxChargingRecord kxChargingRecordCheck = new KxChargingRecord();
        kxChargingRecordCheck.setUserId(getUserId());
        kxChargingRecordCheck.setChargingStatus(Constants.ChargingStatus.INTCHARGING);
        List<KxChargingRecord> kxChargingRecordChecks = kxChargingRecordService.selectKxChargingRecordList(kxChargingRecordCheck);
        if (kxChargingRecordChecks.size() >= Constants.USER_TOTAL_CHARGING) {
            return AjaxResult.error("同时最多支持" + Constants.USER_TOTAL_CHARGING + "辆车充电");
        }
        // 获取当前设备的信息
        KxEquip kxEquip = kxEquipService.getKxEquipByEquipNo(equipNo);
        if (ObjectUtils.isEmpty(kxEquip)) {
            return AjaxResult.error("充电桩不存在");
        }

        // 检查当前插座号是否存在
        if (channelNo < 1 || channelNo > kxEquip.getChannelNum()) {
            return AjaxResult.error("插座号不存在");
        }
        // 判定是否允许漫游充电

        // 检查当前插座是否被使用
        kxChargingRecordCheck.setUserId(null);
        kxChargingRecordCheck.setEquipNo(equipNo);
        kxChargingRecordCheck.setChannelNo(channelNo);
        List<KxChargingRecord> kxChargingRecordChecks1 = kxChargingRecordService.selectKxChargingRecordList(kxChargingRecordCheck);
        if (kxChargingRecordChecks1.size() > 0) {
            return AjaxResult.error("该插座正在充电");
        }
        // 检查是否有余额，或者是否有先消费方案。如果是先消费则直接下一步，否则提示不能充电。
        KxChargingScheme kxChargingScheme = kxChargingSchemeService.selectKxChargingSchemeByChargingSchemeId(kxEquip.getChargingSchemeId());
        KxUserInfo kxUserInfo = kxUserInfoService.selectKxUserInfoByUserId(getUserId());
        BigDecimal lostBalance = kxUserInfo.getBalance().add(kxUserInfo.getGive());
        if (lostBalance.compareTo(BigDecimal.ZERO) == -1) {
            return AjaxResult.error("当前账户金额：" + lostBalance + "元,请先充值");
        }
        // 不允许后付费
        if (kxChargingScheme.getIsPayLater() == Constants.YesOrNo.NO && lostBalance.compareTo(kxChargingScheme.getStartPrice()) == -1) {
            return AjaxResult.error("当前账户金额：" + lostBalance + "元不满足起充金额" + kxChargingScheme.getStartPrice() + "元,请先充值");
        }

        // 创建充电记录
        KxChargingRecord kxChargingRecord = new KxChargingRecord();
        kxChargingRecord.setEquipId(kxEquip.getEquipId());
        kxChargingRecord.setEquipNo(kxEquip.getEquipNo());
        kxChargingRecord.setChannelNo(channelNo);
        kxChargingRecord.setUserId(getUserId());
        kxChargingRecord.setUserName(kxUserInfo.getUserName());
        kxChargingRecord.setEquipType(kxEquip.getEquipType());
        kxChargingRecord.setChargingSchemeId(kxEquip.getChargingSchemeId());
        kxChargingRecord.setAmount(BigDecimal.ZERO);
        kxChargingRecord.setDegree(BigDecimal.ZERO);
        kxChargingRecord.setNumTimes(0);
        kxChargingRecord.setEndType(Constants.EndType.InitChannel);
        kxChargingRecord.setPlanChargingTime(planChargingTime==0?kxChargingScheme.getMaxChargingTime():planChargingTime);
        kxChargingRecord.setChargingPower(0);
        kxChargingRecord.setMaxChargingPower(0);
        kxChargingRecord.setUpdateTime(DateUtils.getNowDate());
        kxChargingRecord.setStartPrice(kxChargingScheme.getStartPrice());
        kxChargingRecord.setChargingStatus(Constants.ChargingStatus.STARTCHARGING);
        kxChargingRecord.setChargingFullNotStop(chargingFullNotStop);
        JSONObject jsonObject = kxEquipService.setChannel(equipNo, String.valueOf(channelNo), Constants.SetChannelState.open, String.valueOf(planChargingTime==0?kxChargingScheme.getMaxChargingTime():planChargingTime), String.valueOf(chargingFullNotStop));
        if (ObjectUtils.isNotEmpty(jsonObject) && ObjectUtils.isNotEmpty(jsonObject.get("chargeno")) && "1".equals(jsonObject.getString("result"))) {
            kxChargingRecord.setChargingStatus(Constants.ChargingStatus.INTCHARGING);
            try {
                int insertKxChargingRecord = kxChargingRecordService.insertKxChargingRecord(kxChargingRecord);
                if (insertKxChargingRecord == 1) {
                    // 更新充电次数，更新常用电站
                    KxUserInfo updateKxUserInfo = new KxUserInfo();
                    updateKxUserInfo.setUserId(getUserId());
                    updateKxUserInfo.setChargingTimes(kxUserInfo.getChargingTimes() + 1);
                    updateKxUserInfo.setCommonUsed(kxEquip.getEquipId());
                    kxUserInfoService.updateKxUserInfo(updateKxUserInfo);
                    return AjaxResult.success("打开插座成功");
                } else {
                    logger.info(getUsername() + " 打开设备: " + equipNo + " 插座: " + channelNo + " 失败,并创建充电记录失败");
                    kxEquipService.onlyCloseChannel(equipNo, String.valueOf(channelNo));
                    return AjaxResult.error("创建充电记录失败");
                }
            } catch (Exception e) {
                logger.info(getUsername() + " 打开设备: " + equipNo + " 插座: " + channelNo + " 失败,并创建充电记录失败");
                kxEquipService.onlyCloseChannel(equipNo, String.valueOf(channelNo));
                return AjaxResult.error("创建充电记录失败");
            }
        } else {
            logger.info(getUsername() + " 打开设备: " + equipNo + " 插座: " + channelNo + " 失败,并结束充电");
            kxEquipService.onlyCloseChannel(equipNo, String.valueOf(channelNo));
            return AjaxResult.error("打开插座失败");
        }
    }
    @RequestMapping(value="/closeChannel",method=RequestMethod.POST)
    public AjaxResult closeChannel(String equipNo,int channelNo){
        try {
            kxEquipService.closeChannel(equipNo,channelNo,Constants.EndType.CloseChannel, true);
            return AjaxResult.success();
        }catch (Exception e){
            return AjaxResult.error(e.getMessage());
        }
    }

    @Resource
    private ImageUtils imageUtils;
    @ApiOperation(value = "获取生成的二维码", notes = "权限需求: wpWarningResult_get_by_id")
    @RequestMapping(value = "/getEquipQR", method = RequestMethod.GET)
    public ResponseEntity<byte[]> getEquipQR(String equipNo, Integer channelNo){
        byte[] byteFile = new byte[0];
        HttpHeaders headers = new HttpHeaders();
        //二进制流
        headers.setContentType(MediaType.valueOf("image/png"));
        //响应头
        headers.add("Accept-Ranges", "bytes");
        String fileName = equipNo+"-"+channelNo+".png";

        headers.setContentDispositionFormData("attachment",fileName);
        try {
            String filePath = "logs/"+ UUID.fastUUID()+".png";
            imageUtils.getQRCode(equipNo,channelNo,filePath);
            File file = new File(filePath);
            //文件转流
            byteFile = FileUtils.readFileToByteArray(file);
            new File(filePath).delete();
        } catch (FileNotFoundException e){
            logger.info("文件不存在"+e);
            return new ResponseEntity<>(byteFile, headers, HttpStatus.OK);
        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity<>(byteFile, headers, HttpStatus.INTERNAL_SERVER_ERROR);
        }
        return new ResponseEntity<>(byteFile, headers, HttpStatus.OK);
    }
    /**
     * 站长获取充电中的插座
     * @param equipNo
     * @return
     */
    @RequestMapping(value = "/getUsedChannels", method = RequestMethod.GET)
    public AjaxResult getUsedChannels(String equipNo){
        JSONObject info = new JSONObject();
        KxEquip kxEquip = kxEquipService.getKxEquipByEquipNo(equipNo);
        info.put("equipId",kxEquip.getEquipId());
        //
        info.put("equipNo",kxEquip.getEquipNo());
        info.put("equipType",kxEquip.getEquipType());
        info.put("equipName",kxEquip.getEquipName());
        info.put("channelNum",kxEquip.getChannelNum());// 插座总数
        // 获取充电中的插座号
        KxChargingRecord kxChargingRecord = new KxChargingRecord();
        kxChargingRecord.setEquipId(kxEquip.getEquipId());
        kxChargingRecord.setChargingStatus(Constants.ChargingStatus.INTCHARGING);
        List<Integer> kxChargingRecordList = kxChargingRecordService.getChargingChannelNos(kxChargingRecord);
        info.put("chargingChannels",kxChargingRecordList);
        return AjaxResult.success(info);
    }
    @RequestMapping(value = "/getCommonUsed", method = RequestMethod.GET)
    public AjaxResult getCommonUsed(){
        KxUserInfo kxUserInfo = kxUserInfoService.selectKxUserInfoByUserId(getUserId());
        KxEquip kxEquip = kxEquipService.selectKxEquipByEquipId(kxUserInfo.getCommonUsed());
        if(ObjectUtils.isNotEmpty(kxEquip)){
            JSONObject info = new JSONObject();
            info.put("equipId",kxEquip.getEquipId());
            info.put("equipNo",kxEquip.getEquipNo());
            info.put("equipType",kxEquip.getEquipType());
            info.put("equipName",kxEquip.getEquipName());
            info.put("channelNum",kxEquip.getChannelNum());// 插座总数
            // 获取充电中的插座号
            KxChargingRecord kxChargingRecord = new KxChargingRecord();
            kxChargingRecord.setEquipId(kxEquip.getEquipId());
            kxChargingRecord.setChargingStatus(Constants.ChargingStatus.INTCHARGING);
            List<Integer> kxChargingRecordList = kxChargingRecordService.getChargingChannelNos(kxChargingRecord);
            info.put("chargingChannels",kxChargingRecordList);
            return AjaxResult.success(info);
        }else {
            return AjaxResult.success("没有常用电站");
        }
    }

}
